package Core;
/*
 *  Author: unknown
 *  Edit: Van
 */
import java.io.InputStream;
import java.util.Vector;

import javax.microedition.lcdui.Graphics;

public class RGBFont 
{
	public int m_iFontHeight = 0;
	public int m_iFontColor = 0xFF000000;
	public int m_iBorderColor = 0xFFEEEEEE;//0xFF000000;
	public boolean m_hasBorder = false;
	
	private int  m_iTotalChars = 0;
	private char m_aEnumChars[] = null; //array that stores all chars in game
	private int	 m_aiFontImageData[] = null; //array that stores data of font's image
	private byte m_bFontWidth[] = null; // array that stores width of all chars in game
	private byte m_abFontPackData[][] = null; //array that stores font data of all chars in game
	
	private int m_iBitPerPixel = 1;
	private int m_iBitToShift = 0;
	private int m_iBitAND = 0;
	private int m_iBitToCheckBorder = 0;
	private int m_iScale = 0;
	
	public void destroy(){
	}
	
	public RGBFont(String strPackageName)
	{
		LoadFont(strPackageName);
	}
	
	public boolean LoadFont(String strPackageName)
	{
		System.out.println("LoadFont LoadFont");
		if (strPackageName.charAt(0) != '/')
		{
			strPackageName = "/" + strPackageName;
		}
		
		try
		{
			InputStream packStream = "".getClass().getResourceAsStream(strPackageName);
			
			if (packStream == null)
			{
				return false;
			}
			// return value from read() method of InputStream
			int iCurrValue = 0;
				
			//get num of character
			m_iTotalChars = packStream.read();
			if (m_iTotalChars == -1)
			{
				return false;
			}
			iCurrValue = packStream.read();
			if (iCurrValue == -1)
			{
				return false;
			}
			
			m_iTotalChars = m_iTotalChars|(iCurrValue<<8);
			
			//allocate mem
			m_aEnumChars = new char[m_iTotalChars];
			m_bFontWidth = new byte[m_iTotalChars];
			m_abFontPackData = new byte[m_iTotalChars][];
			
			//get height of font
			m_iFontHeight = packStream.read();
			if (m_iFontHeight == -1)
			{
				return false;
			}
			//allocate mem for decoded data buffer
			m_aiFontImageData = new int[m_iFontHeight * m_iFontHeight * 2];
			
			//get bits system
			m_iBitPerPixel = packStream.read();
			
			m_iBitToShift = 4 - m_iBitPerPixel;
			if (m_iBitPerPixel == 1)
			{
				m_iBitAND = 0x07;
				m_iBitToCheckBorder = 0x01;
				m_iScale = 0;
			}
			else
			{
				m_iBitAND = 0x03;
				m_iBitToCheckBorder = 0x03;
				m_iScale = 1;
			}
			
			//get data of each character
			byte[] abUnicodeBuffer = new byte[2];
			int iDataSize = 0;
			for (int i = 0; i < m_iTotalChars; i++)
			{
				//Read Unicode of character
				iCurrValue = packStream.read(abUnicodeBuffer, 0, 2);
				if (iCurrValue == -1)
				{
					return false;
				}
				m_aEnumChars[i] = (char)((abUnicodeBuffer[0] & 0xFF) | ((abUnicodeBuffer[1] & 0xFF) << 8));
				
				//Read width of character in this font
				iCurrValue = packStream.read();
				if (iCurrValue == -1)
				{
					return false;
				}
				m_bFontWidth[i] = (byte)iCurrValue;
				
				//Read font data of character
				iDataSize = 1 + ((m_bFontWidth[i] * m_iFontHeight) >> m_iBitToShift);
				
				m_abFontPackData[i] = new byte[iDataSize];
				iCurrValue = packStream.read(m_abFontPackData[i], 0, iDataSize);
				if (iCurrValue == -1)
				{
					return false;
				}
			}
			
			packStream.close();
		}
		catch (Exception ex)
		{
			System.out.println("ERROR : "+ ex.toString());
			
			
			return false;
		}
		
		return true;
	}
	
	
	public void SetColor(int iNewColor)
	{
		m_iFontColor = iNewColor | 0xFF000000;
	}
	
	
	public void SetBorderColor(int iNewColor)
	{
		m_hasBorder = true;
		m_iBorderColor = iNewColor | 0xFF000000;
	}
	
	
	public void SetBorderHidden()
	{
		m_hasBorder = false;
	}
	
	public int GetColor()
	{
		return m_iFontColor;
	}
	
	
	public int DrawChar(Graphics g, char ch, int x, int y)
	{
		int iCharIndex = MapChar(ch);
		
		if (iCharIndex == -1)
		{
			return 0;
		}
		
		DecodeFont(iCharIndex, m_aiFontImageData);
		int iCharWidth = m_bFontWidth[iCharIndex];
		g.drawRGB(m_aiFontImageData, 0, iCharWidth, x, y, iCharWidth, m_iFontHeight, true);
		
		return iCharWidth;
	}
	
	public int DrawCharPixel(Graphics g, char ch, int x, int y)
	{
		int iCharIndex = MapChar(ch);
		
		if (iCharIndex == -1)
		{
			return 0;
		}
		
		int iCharWidth = m_bFontWidth[iCharIndex];
		int iCharSize = m_iFontHeight * iCharWidth;
		int iByteOfPixel = 0;
		int iBitIndex = 0;
		int iDrawingX = x;
		
		//If font has no border -> need to call setColor() only 1 time.
		g.setColor(m_iFontColor);
		for (int i = 0; i < iCharSize; i++)
		{
			iByteOfPixel = i >> m_iBitToShift;
			iBitIndex = ((i & m_iBitAND) << m_iScale);
			
			if (((m_abFontPackData[iCharIndex][iByteOfPixel] >> iBitIndex) & m_iBitToCheckBorder) == 1)
			{
				g.drawLine(iDrawingX, y, iDrawingX, y); //Draw 1 pixel
			}
			else if (m_hasBorder && (((m_abFontPackData[iCharIndex][iByteOfPixel] >> iBitIndex) & m_iBitToCheckBorder) == 2))
			{
				g.setColor(m_iBorderColor);
				g.drawLine(iDrawingX, y, iDrawingX, y); //Draw 1 pixel
				g.setColor(m_iFontColor);
			}
			
			iDrawingX++;
			if ((iDrawingX - x) >= iCharWidth)
			{
				iDrawingX = x;
				y++;
			}
		}
		
		return iCharWidth;
	}
	
	public int getHeight()
	{
		return m_iFontHeight;
	}
	
	
	public int GetCharWidth(char ch)
	{
		int iCharIndex = MapChar(ch);
		
		if (iCharIndex == -1)
		{
			return 0;
		}
		
		return m_bFontWidth[iCharIndex];
	}
	
	
	private int MapChar(char ch)
	{
		int iLeftIndex = 0;
		int iRightIndex = m_iTotalChars - 1;
		int iMiddleIndex = 0;
		
		while (iLeftIndex <= iRightIndex)
		{
			iMiddleIndex = (iLeftIndex + iRightIndex) >> 1;
			
			if (m_aEnumChars[iMiddleIndex] == ch)
			{
				return iMiddleIndex;
			}
			else if (m_aEnumChars[iMiddleIndex] < ch)
			{
				iLeftIndex = iMiddleIndex+1;
			}
			else
			{
				iRightIndex = iMiddleIndex-1;
			}
		}
		
		return -1;
	}
	
	
	private void DecodeFont(int iCharID, int[] aiRGB)
	{
		int iCharSize = m_iFontHeight * m_bFontWidth[iCharID];
		int iByteOfPixel = 0;
		int iBitIndex = 0;
		//int shift_bit = 0;
		if (aiRGB == null)
		{
			aiRGB = new int[iCharSize];
		}
		
		for (int i = 0; i < iCharSize; i++)
		{
			iByteOfPixel = i >> m_iBitToShift;
			iBitIndex = ((i & m_iBitAND) << m_iScale);
			
			if (((m_abFontPackData[iCharID][iByteOfPixel] >> iBitIndex) & m_iBitToCheckBorder) == 1)
			{
				aiRGB[i] = m_iFontColor | 0x0F000000;
			}
			else if (m_hasBorder && (((m_abFontPackData[iCharID][iByteOfPixel] >> iBitIndex) & m_iBitToCheckBorder) == 2))
			{
				aiRGB[i] = m_iBorderColor | 0x0F000000;
			}
			else
			{
				aiRGB[i] = 0;
			}
		}
	}
	
	 public void drawString(Graphics g, String st, int x, int y, int align, int color) 
	 {
		 if(st == null || st.length()==0) return;
		 if(align == 1){ // Right
			 x -= stringWidth(st);
		 } else if (align == 2){ // Center
			 x -= (stringWidth(st)>>1);
		 }
		SetColor(color);
 		for (int i = 0; i < st.length() ; i++)
 		{
 			int c = (int)(st.charAt(i));
			char ch = (char)c;
			DrawChar(g,ch, x, y);
			x = x + GetCharWidth(ch);//+1;
			if (ch == ' ')
			{
				x += 3;// space 
			}
 		}
	 }
	 
	 public  void drawString(Graphics g, String string, int startX, int startY, int width, int align, int color)
	 {
		 	//System.out.println(string);
		 	SetColor(0xffffff);
		 	
		 	String[] stringArray = splitStrInLine(string,width);
		 	
		 	int x = startX;
		 	int y = startY;
		 	for (int k = 0; k < stringArray.length ; k++)
		 	{
		 		SetColor(0xffffff);
	 			if (k%2 ==0)
	 				SetColor(0xff0000);
		 		for (int i = 0; i < stringArray[k].length() ; i++)
		 		{
		 			
		 			
		 			int c = (int) (stringArray[k].charAt(i));
					char ch = (char)c;
					//System.out.println("      char:"+ch);
					DrawChar(g,ch, x, y);
					x = x + GetCharWidth(ch)+1;
					if (ch == ' ')
					{
						x += 3;// space 
					}
				
		 		}
		 		x = startX;
		 		y += 13; //line space
		 	}
		 	
			

		 
	 }
	 public int stringWidth(String st)
	 {
	        int len = 0;
	        for (int i = 0; i < st.length() ; i++)
			{
	        	int c = (int) (st.charAt(i));
	        	char ch = (char)c;
				len += GetCharWidth(ch);//+1;
				if (ch == ' ')
				{
					len += 3;// space
				}
			}
	        return len;
	 }
	 /** 1: be cut ; 0: No or nil */
	 public String stringFix(String st, int width){
		int i = stringPosFix(st, width); 
        if(i == 0) return "0";
		return (i < st.length() ? "1" : "0") + st.substring(0, i) ;
	 }
	 public String stringFixEtc(String st, int width){
		int i = stringPosFix(st, width); 
        if(i == 0) return "";
		return (i < st.length() ? ( i > 3 ? st.substring(0, i-3) + "..." : st.substring(0, i)) : st);
	 }
	 public int stringPosFix(String st, int width){
        int i = 0, len = 0;
        for (; i < st.length()  && len < width; i++){
        	char c = st.charAt(i);
			len += GetCharWidth(c);
			if (c == ' ') len += 3;
		}
        return i;
	 }
	 public String[] splitStrInLine(String src, int lineWidth)
	 {
		 if(src == null || (src.length() == 0)) return null;
		 Vector list = new Vector();
		 int srclen = src.length();
		 String tem = "";
		 int start = 0, end = 0;
		 while (true)
		 {
			 while (stringWidth(tem) < lineWidth)
			 {
				 if(src.charAt(end) == '\n')
					 break;
				 tem += src.charAt(end);
				 end++;
				 if (end == srclen)
					 break;
			 }
			 if (end < srclen && src.charAt(end) != ' ' && src.charAt(end) != '\n')
			 {
				 int endAnyway = end;
				 while (true)
				 {
					 if (end == start)
						 break;
					 if (src.charAt(end - 1) != ' ' && src.charAt(end) == ' ')
						 break;
					 end--;
				 }
				 if (end == start)
					 end = endAnyway;
			 }
			 list.addElement(src.substring(start, end));
			 if (end == srclen)
				 break;
			 start = end + 1;
			 while (start < srclen && src.charAt(start) == ' ')
				 start++;
			 if (start == srclen)
				 break;
			 end = start;
			 tem = "";
		 }
		 String[] strs = new String[list.size()];
		 for (int i = 0; i < list.size(); i++)
		 {
			 strs[i] = (String) list.elementAt(i);
		 }
		 return strs;
	 }
}
